Xen support for sysenter/exit on x86_32 when supervisor_mode_kernel is
authorIan.Campbell@xensource.com <Ian.Campbell@xensource.com>
Fri, 21 Apr 2006 16:19:29 +0000 (17:19 +0100)
committerIan.Campbell@xensource.com <Ian.Campbell@xensource.com>
Fri, 21 Apr 2006 16:19:29 +0000 (17:19 +0100)
enabled.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
xen/arch/x86/cpu/common.c
xen/arch/x86/traps.c
xen/arch/x86/x86_32/traps.c
xen/include/asm-x86/cpufeature.h
xen/include/public/callback.h

index cfcae8cb85ea67e0f829ee203b859b84ac803dda..63237c82f4112ce7b1ac48acf548814fe518a1c6 100644 (file)
@@ -575,6 +575,8 @@ void __devinit cpu_init(void)
 #if defined(CONFIG_X86_32)
        t->ss0  = __HYPERVISOR_DS;
        t->esp0 = get_stack_bottom();
+       if ( supervisor_mode_kernel && cpu_has_sep )
+               wrmsr(MSR_IA32_SYSENTER_ESP, &t->esp1, 0);
 #elif defined(CONFIG_X86_64)
        /* Bottom-of-stack must be 16-byte aligned! */
        BUG_ON((get_stack_bottom() & 15) != 0);
index 76fd4a16dbf0ff2e4b1798b87c605364a8a20551..6b256e3877e325dc7bb14b598001036f17e44af7 100644 (file)
@@ -425,7 +425,8 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
         clear_bit(X86_FEATURE_DE,  &d);
         clear_bit(X86_FEATURE_PSE, &d);
         clear_bit(X86_FEATURE_PGE, &d);
-        clear_bit(X86_FEATURE_SEP, &d);
+        if ( !supervisor_mode_kernel )
+            clear_bit(X86_FEATURE_SEP, &d);
         if ( !IS_PRIV(current->domain) )
             clear_bit(X86_FEATURE_MTRR, &d);
     }
index dfba38c56666a7e6804746eb3b972fbc124a2f3c..cbd15f280151c8e24ec3c60aab593ce93e88160d 100644 (file)
@@ -318,6 +318,16 @@ void init_int80_direct_trap(struct vcpu *v)
         set_int80_direct_trap(v);
 }
 
+#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
+static void do_update_sysenter(void *info)
+{
+    xen_callback_t *address = info;
+
+    wrmsr(MSR_IA32_SYSENTER_CS, address->cs, 0);
+    wrmsr(MSR_IA32_SYSENTER_EIP, address->eip, 0);
+}
+#endif
+
 static long register_guest_callback(struct callback_register *reg)
 {
     long ret = 0;
@@ -337,6 +347,15 @@ static long register_guest_callback(struct callback_register *reg)
         v->arch.guest_context.failsafe_callback_eip = reg->address.eip;
         break;
 
+#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
+    case CALLBACKTYPE_sysenter:
+        if ( ! cpu_has_sep )
+            ret = -EINVAL;
+        else if ( on_each_cpu(do_update_sysenter, &reg->address, 1, 1) != 0 )
+            ret = -EIO;
+        break;
+#endif
+
     case CALLBACKTYPE_nmi:
         ret = register_guest_nmi_callback(reg->address.eip);
         break;
index 0a815ac6a7ffd3a105ffa8c93257f37a4a6f8c89..a092a83ad5b9ca0fe34b5ad5ac8dc95e99ba98af 100644 (file)
 #define cpu_has_pae            boot_cpu_has(X86_FEATURE_PAE)
 #define cpu_has_pge            boot_cpu_has(X86_FEATURE_PGE)
 #define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
+#define cpu_has_sep            boot_cpu_has(X86_FEATURE_SEP)
 #define cpu_has_mtrr           boot_cpu_has(X86_FEATURE_MTRR)
 #define cpu_has_mmx            boot_cpu_has(X86_FEATURE_MMX)
 #define cpu_has_fxsr           boot_cpu_has(X86_FEATURE_FXSR)
 #define cpu_has_pae            1
 #define cpu_has_pge            1
 #define cpu_has_apic           boot_cpu_has(X86_FEATURE_APIC)
+#define cpu_has_sep            0
 #define cpu_has_mtrr           1
 #define cpu_has_mmx            1
 #define cpu_has_fxsr           1
index 27877c72ad40e841a9a7dbc9f44cb2657116731f..820fffd78c30af00f4cc5f828223eb8d17fb3022 100644 (file)
 #define CALLBACKTYPE_event                 0
 #define CALLBACKTYPE_failsafe              1
 #define CALLBACKTYPE_syscall               2 /* x86_64 only */
+/*
+ * sysenter is only available on x86_32 with the
+ * supervisor_mode_kernel option enabled.
+ */
+#define CALLBACKTYPE_sysenter              3
 #define CALLBACKTYPE_nmi                   4
 
 /*